<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
    <title>Hoodoo::ActiveRecord::Secure::ClassMethods</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <link rel="stylesheet" href="../../../../css/reset.css" type="text/css" media="screen" />
<link rel="stylesheet" href="../../../../css/main.css" type="text/css" media="screen" />
<link rel="stylesheet" href="../../../../css/github.css" type="text/css" media="screen" />
<script src="../../../../js/jquery-1.3.2.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../../../../js/jquery-effect.js" type="text/javascript" charset="utf-8"></script>
<script src="../../../../js/main.js" type="text/javascript" charset="utf-8"></script>
<script src="../../../../js/highlight.pack.js" type="text/javascript" charset="utf-8"></script>

</head>

<body>
    <div class="banner">
        <h1>
            <span class="type">Module</span>
            Hoodoo::ActiveRecord::Secure::ClassMethods
        </h1>
        <ul class="files">
            <li><a href="../../../../files/lib/hoodoo/active/active_record/secure_rb.html">lib/hoodoo/active/active_record/secure.rb</a></li>
        </ul>
    </div>
    <div id="bodyContent">
        <div id="content">
    <div class="description">
      
<p>Collection of class methods that get defined on an including class via <a
href="../Secure.html#method-c-included">Hoodoo::ActiveRecord::Secure.included</a>.</p>

    </div>








    <!-- Method ref -->
    <div class="sectiontitle">Methods</div>
    <dl class="methods">
        <dt>S</dt>
        <dd>
          <ul>
              <li>
                <a href="#method-i-secure">secure</a>,
              </li>
              <li>
                <a href="#method-i-secure_with">secure_with</a>,
              </li>
              <li>
                <a href="#method-i-secured_with">secured_with</a>
              </li>
          </ul>
        </dd>
    </dl>







      <!-- Section constants -->
      <div class="sectiontitle">Constants</div>
      <table border='0' cellpadding='5'>
          <tr valign='top' id='DEFAULT_SECURE_PROC'>
            <td class="attr-name">DEFAULT_SECURE_PROC</td>
            <td>=</td>
            <td class="attr-value"><pre>Proc.new { | model_class, database_column_name, session_field_value | [ { database_column_name =&gt; session_field_value } ] }</pre></td>
          </tr>
            <tr valign='top'>
              <td>&nbsp;</td>
              <td colspan="2" class="attr-desc"><p>Internal.</p>

<p>See <a href="ClassMethods.html#method-i-secure">secure</a> for details -
this is the Proc used by default if no alternative argument generator is
given in the longhand form&#39;s value Hash&#39;s <code>:using</code> key.</p></td>
            </tr>
      </table>



    <!-- Methods -->
      <div class="sectiontitle">Instance Public methods</div>
        <div class="method">
          <div class="title method-title" id="method-i-secure">
              <b>secure</b>( context )
            <a href="../../../../classes/Hoodoo/ActiveRecord/Secure/ClassMethods.html#method-i-secure" name="method-i-secure" class="permalink">Link</a>
          </div>

            <div class="description">
              <p>The core of out-of-the-box <a href="../../../Hoodoo.html">Hoodoo</a> data
access security layer.</p>

<p>Parameters:</p>
<dl class="rdoc-list note-list"><dt>context
<dd>
<p><a href="../../Services/Context.html">Hoodoo::Services::Context</a>
instance describing a call context. This is typically a value passed to one
of the <a
href="../../Services/Implementation.html">Hoodoo::Services::Implementation</a>
instance methods that a resource subclass implements.</p>
</dd></dl>

<h2 id="method-i-secure-label-Overview">Overview</h2>

<p>In most non-trivial systems, people calling into the system under a Session
will have limited access to resource records. Often the broad pattern is:
Someone can only see what they create. Maybe there&#39;s a superuser-like
monitoring concept of someone who can see what everyone creates… In any
event, there needs to be some kind of support for this.</p>

<p>In the <a href="../../../Hoodoo.html">Hoodoo</a> generic case, it&#39;s
tackled at several levels.</p>
<ul><li>
<p>A Caller object can describe fields that are identify who that Caller is
(which may be as simple as the Caller instance&#39;s resource <a
href="../UUID.html">UUID</a>, or may include additional concepts specific
to the API being designed/implemented).</p>
</li><li>
<p>A Session instance is bound to a particular Caller. Someone calling the API
creates a Session using a caller ID and secret, and gains whatever access
permissions and data privileges it describes.</p>
</li><li>
<p>Custom implementations of a Session resource and Caller resource endpoint
might add in other identifying fields to the session payload too.
That&#39;s what the Session&#39;s <code>identity</code> section is for. See
<a
href="../../Services/Session.html#attribute-i-identity">Hoodoo::Services::Session#identity</a>.</p>
</li><li>
<p>When resource endpoint implementations create data, they have an
opportunity to use a database field to record (say) the caller <a
href="../UUID.html">UUID</a> and/or some other session value(s) in indexed
table columns along the lines of “creating_caller_uuid”, or similar. This
way, the “who made me” information is preserved.</p>
</li><li>
<p>When resource endpoints read back any data from the database (for show,
list, update or delete actions) the “who made me” information needs to be
compared against &#39;what the session is allowed to see&#39;. That&#39;s
in the Session&#39;s <code>scoping</code> section. See <a
href="../../Services/Session.html#attribute-i-scoping">Hoodoo::Services::Session#scoping</a>.
For example, a custom Session resource endpoint might record one or more
caller UUIDs in “scoping.authorised_caller_uuids”.</p>
</li></ul>

<p>Given things along this line, resource endpoints would have to individually
scope <a href="../../ActiveRecord.html">ActiveRecord</a> <code>find</code>
calls to make sure that it only dealt with database records where the
&#39;who made me&#39; data matched up with the &#39;what can this Session
see&#39;. That can be done but it might be error prone, especially if a lot
of resource endpoints all have the same data access scoping rules.</p>

<h2 id="method-i-secure-label-Automatic+session-based+finder+scoping">Automatic session-based finder scoping</h2>

<p>That&#39;s where the <a href="../../ActiveRecord.html">ActiveRecord</a>
secure context extension comes in. Models declare <em>mappings</em> between
database fields and fields in the Session&#39;s <code>scoping</code>
container. An ActiveRecord::Relation is returned which produces a simple
query along the lines of:</p>

<pre><code>Model.where( :database_field =&gt; session.scoping.scoped_field )
</code></pre>

<p>At the time of writing, only simple matches of as shown above can be
defined; bespoke resource endpoint implementation code would be needed for
something more complex. All you can do is make sure that one or more fields
in the database match with one more fields in the Session scoping data.</p>

<p>Taking the examples of a database column <code>creating_caller_uuid</code>
and a Session scoping entry called <code>authorised_caller_uuids</code>, a
model would do the following to declare the mapped connection between
database and session:</p>

<pre><code>class Audit &lt; ActiveRecord::Base
  include Hoodoo::ActiveRecord::Secure

  secure_with( {
    :creating_caller_uuid =&gt; :authorised_caller_uuids
  } )
end
</code></pre>

<p>Then, inside subclass implementation of (for example) <a
href="../../Services/Implementation.html#method-i-list">Hoodoo::Services::Implementation#list</a>:</p>

<pre><code>def list( context )
  secure_scope = Audit.secure( context )
end
</code></pre>

<p>The &#39;secure_scope&#39; is just an ActiveRecord::Relation instance; you
could call <code>to_sql</code> on the result for debugging and print the
result to console if you wanted to see the query built up so far.
Otherwise, any of the ActiveRecord::QueryMethods can be called; see:</p>

<p><a
href="http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html">api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html</a></p>

<p>The most common use cases, though, involve finding a specific record or
listing records. <a href="../Finder.html">Hoodoo::ActiveRecord::Finder</a>
provides much higher level constructs that build on top of <a
href="ClassMethods.html#method-i-secure">secure</a> and you are strongly
encouraged to use these wherever possible, rather than calling <a
href="ClassMethods.html#method-i-secure">secure</a> directly.</p>

<p>For more advanced query conditions that a single database column checked
against a session value with an implicit <code>AND</code>, see later.</p>

<h2 id="method-i-secure-label-Important-21">Important!</h2>

<p>If you state a model must be secured by one or more fields, then:</p>
<ul><li>
<p>If there is no session at all in the given context, <em>or</em></p>
</li><li>
<p>The session has no scoping data, <em>or</em></p>
</li><li>
<p>The session scoping data does not have one or more of the fields that the
<a href="ClassMethods.html#method-i-secure_with">secure_with</a> map&#39;s
values describe, <em>then</em></p>
</li></ul>

<p>…the returned scope <strong>will</strong> <strong>find</strong>
<strong>no</strong> <strong>results</strong>, by design. The default
failure mode is to reveal no data at all.</p>

<h2 id="method-i-secure-label-Rendering+resources">Rendering resources</h2>

<p>Models aren&#39;t directly connected to Resource representations, but since
the security later interfaces with session data herein, there is clearly an
intersection of concepts. Even though fields in a Model may not map
directly to fields in a related Resource (or many Models might contribute
to a Resource), the security scoping rules that led to the limitations on
data retrieval may be useful to an API caller. The API basic definitions
support this through a <code>secured_with</code> standard (but optional)
resource field.</p>

<p>The <code>secured_with</code> field&#39;s value is an object of key/value
pairs. Its contents depend on how the <a
href="ClassMethods.html#method-i-secure_with">secure_with</a> method is
used in a model. The <a
href="ClassMethods.html#method-i-secure_with">secure_with</a> call actually
supports <em>two</em> modes of operation. One is as already shown above;
suppose we have:</p>

<pre><code>secure_with( {
  :creating_caller_uuid =&gt; :authorised_caller_uuids,
  :programme_code       =&gt; :authorised_programme_codes
} )
</code></pre>

<p>If <a
href="../../Presenters/Base.html#method-c-render_in">Hoodoo::Presenters::Base.render_in</a>
is called and an instance of a model with the above declaration is passed
in the <code>secured_with</code> option, then the keys from the declaration
appear in the resource representation&#39;s <code>secured_with</code>
field&#39;s object and the values are the <em>actual</em> scoping values
which were used, i.e. the rendered data would contain:</p>

<pre><code>{
  &quot;id&quot;: &quot;&lt;UUID&gt;&quot;,
  &quot;kind&quot;: &quot;Example&quot;,
  &quot;created_at&quot;: &quot;2015-04-30T16:25:17+12:00&quot;,
  &quot;secured_with&quot;: {
    &quot;creating_caller_uuid&quot;: &quot;&lt;UUID&gt;&quot;,
    &quot;programme_code&quot;: &quot;&lt;code&gt;&quot;
  },
  ...
}</code></pre>

<p>This binds the field values in the model to the values in the rendered
resource representation, though; and what if we only wanted (say) the
“creating_caller_uuid” to be revealed, but did not want to show the
“programme_code” value? To do this, instead of passing a Symbol in the
values of the <a
href="ClassMethods.html#method-i-secure_with">secure_with</a> options, you
provide a Hash of options for that particular security entry. Option keys
are Symbols:</p>
<dl class="rdoc-list note-list"><dt><code>session_field_name</code>
<dd>
<p>This is the field that&#39;s looked up in the session&#39;s scoping
section.</p>
</dd><dt><code>resource_field_name</code>
<dd>
<p>This is the name that&#39;ll appear in the rendered resource.</p>
</dd><dt><code>hide_from_resource</code>
<dd>
<p>If present and set to <code>true</code>, the entry will not be shown; else
it is shown by default (if you&#39;re passing in a model instance to a
render call via the <code>secured_with</code> option it is assumed that you
explicitly <em>do</em> want to include this kind of information rather than
hide it).</p>
</dd><dt><code>using</code>
<dd>
<p>See the <em>Advanced</em> <em>query</em> <em>conditions</em> section later
for details.</p>
</dd></dl>

<p>To help clarify the above, the following two calls to <a
href="ClassMethods.html#method-i-secure_with">secure_with</a> have exactly
the same effect.</p>

<pre><code>secure_with( {
  :creating_caller_uuid =&gt; :authorised_caller_uuids
} )

# ...is equivalent to...

secure_with( {
  :creating_caller_uuid =&gt; {
    :session_field_name  =&gt; :authorised_caller_uuids,
    :resource_field_name =&gt; :creating_caller_uuid, # (Or just omit this option)
    :hide_from_resource  =&gt; false # (Or just omit this option)
  }
} )
</code></pre>

<p>Taking the previous example, let&#39;s change the name of the field shown
in the resource and hide the “programme_code” entry:</p>

<pre><code>secure_with( {
  :creating_caller_uuid =&gt; {
    :session_field_name  =&gt; :authorised_caller_uuids,
    :resource_field_name =&gt; :caller_id # Note renaming of field
  },
  :programme_code =&gt; {
    :session_field_name =&gt; :authorised_programme_codes,
    :hide_from_resource =&gt; true
  }
} )
</code></pre>

<p>…would lead to a rendered resource looking something like this:</p>

<pre><code>{
  &quot;id&quot;: &quot;&lt;UUID&gt;&quot;,
  &quot;kind&quot;: &quot;Example&quot;,
  &quot;created_at&quot;: &quot;2015-04-30T16:25:17+12:00&quot;,
  &quot;secured_with&quot;: {
    &quot;caller_id&quot;: &quot;&lt;UUID&gt;&quot;,
  },
  ...
}</code></pre>

<h2 id="method-i-secure-label-Advanced+query+conditions">Advanced query conditions</h2>

<p>A simple implicit <code>AND</code> clause on a single database column might
not be sufficient for your scoping. In this case, the “longhand” Hash form
described for rendering is used, this time including the key
<code>:using</code> to specify a Proc that is executed to return an array
of parameters for <code>where</code>. For example:</p>

<pre><code>secure_with( {
  :creating_caller_uuid =&gt; :authorised_caller_uuids
} )

# ...has this minimal longhand equivalent...

secure_with( {
  :creating_caller_uuid =&gt; {
    :session_field_name =&gt; :authorised_caller_uuids
  }
} )
</code></pre>

<p>This leads to SQL along the following lines:</p>

<pre><code>AND (&quot;model_table&quot;.&quot;creating_caller_uuid&quot; = &#39;[val]&#39;)</code></pre>

<p>…where <code>val</code> is from the Session
<code>authorised_caller_uuids</code> data in the <code>scoping</code>
section (so this might be an SQL <code>IN</code> rather than <code>=</code>
if that data is a multi-element array). Suppose you need to change this to
check that value <em>or</em> something else? Use the <code>:using</code>
key and a Proc. Since <a href="../../ActiveRecord.html">ActiveRecord</a> at
the time of writing lacks a high level way to do &#39;OR&#39; via methods,
it&#39;s easiest and most flexible just to give up and fall to an SQL
string:</p>

<pre><code>or_matcher = Proc.new do | model_class, database_column_name, session_field_value |

  # This example works for non-array and array field values.
  #
  session_field_value = [ session_field_value ].flatten

  [
    &quot;\&quot;#{ database_column_name }\&quot; IN (?) OR \&quot;other_column_name\&quot; IN (?)&quot;,
    session_field_value,
    session_field_value
  ]
end

secure_with( {
  :creating_caller_uuid =&gt; {
    :session_field_name =&gt; :authorised_caller_uuids,
    :using              =&gt; or_matcher
  }
} )
</code></pre>

<p>…yields something like:</p>

<pre><code>AND ( &quot;model_table&quot;.&quot;creating_caller_uuid&quot; = &#39;[val]&#39; OR &quot;model_table&quot;.&quot;other_column_name&quot; = &#39;[val]&#39; )</code></pre>

<p>A Proc specified with <code>:using</code> is called with:</p>
<ul><li>
<p>The model class which is involved in the query.</p>
</li><li>
<p>The name of the database column specified in the <code>secure_with</code>
Hash as the top-level key (e.g. <code>creating_called_uuid</code> above).</p>
</li><li>
<p>The session field <em>value</em> that was recovered under the given key -
the value of <code>session.scoping.authorised_caller_uuids</code> in the
example above.</p>
</li></ul>

<p>You must return _AN ARRAY_ of arguments that will be passed to
<code>where</code> via <code>where( *returned_values )</code> as part of
the wider query chain.</p>
            </div>



            <div class="sourcecode">
              <p class="source-link">
                Source:
                <a href="javascript:toggleSource('method-i-secure_source')" id="l_method-i-secure_source">show</a>
              </p>
              <div id="method-i-secure_source" class="dyn-source">
                <pre><span class="ruby-comment"># File lib/hoodoo/active/active_record/secure.rb, line 372</span>
<span class="ruby-keyword">def</span> <span class="ruby-keyword ruby-title">secure</span>( <span class="ruby-identifier">context</span> )
  <span class="ruby-identifier">prevailing_scope</span> = <span class="ruby-identifier">all</span>() <span class="ruby-comment"># &quot;Model.all&quot; -&gt; returns anonymous scope</span>
  <span class="ruby-identifier">extra_scope_map</span>  = <span class="ruby-identifier">secured_with</span>()

  <span class="ruby-keyword">unless</span> <span class="ruby-identifier">extra_scope_map</span>.<span class="ruby-identifier">nil?</span>
    <span class="ruby-keyword">return</span> <span class="ruby-identifier">none</span>() <span class="ruby-keyword">if</span> <span class="ruby-identifier">context</span>.<span class="ruby-identifier">session</span>.<span class="ruby-identifier">nil?</span> <span class="ruby-operator">||</span> <span class="ruby-identifier">context</span>.<span class="ruby-identifier">session</span>.<span class="ruby-identifier">scoping</span>.<span class="ruby-identifier">nil?</span>

    <span class="ruby-identifier">extra_scope_map</span>.<span class="ruby-identifier">each</span> <span class="ruby-keyword">do</span> <span class="ruby-operator">|</span> <span class="ruby-identifier">model_field_name</span>, <span class="ruby-identifier">key_or_options</span> <span class="ruby-operator">|</span>
      <span class="ruby-identifier">params_proc</span> = <span class="ruby-constant">DEFAULT_SECURE_PROC</span>

      <span class="ruby-keyword">if</span> <span class="ruby-identifier">key_or_options</span>.<span class="ruby-identifier">is_a?</span>( <span class="ruby-constant">Hash</span> )
        <span class="ruby-identifier">session_scoping_key</span> = <span class="ruby-identifier">key_or_options</span>[ <span class="ruby-value">:session_field_name</span> ]
        <span class="ruby-identifier">params_proc</span>         = <span class="ruby-identifier">key_or_options</span>[ <span class="ruby-value">:using</span> ] <span class="ruby-keyword">if</span> <span class="ruby-identifier">key_or_options</span>.<span class="ruby-identifier">has_key?</span>( <span class="ruby-value">:using</span> )
      <span class="ruby-keyword">else</span>
        <span class="ruby-identifier">session_scoping_key</span> = <span class="ruby-identifier">key_or_options</span>
      <span class="ruby-keyword">end</span>

      <span class="ruby-keyword">if</span> <span class="ruby-identifier">context</span>.<span class="ruby-identifier">session</span>.<span class="ruby-identifier">scoping</span>.<span class="ruby-identifier">respond_to?</span>( <span class="ruby-identifier">session_scoping_key</span> )
        <span class="ruby-identifier">args</span> = <span class="ruby-identifier">params_proc</span>.<span class="ruby-identifier">call</span>(
          <span class="ruby-keyword">self</span>,
          <span class="ruby-identifier">model_field_name</span>,
          <span class="ruby-identifier">context</span>.<span class="ruby-identifier">session</span>.<span class="ruby-identifier">scoping</span>.<span class="ruby-identifier">send</span>( <span class="ruby-identifier">session_scoping_key</span> )
        )
        <span class="ruby-identifier">prevailing_scope</span> = <span class="ruby-identifier">prevailing_scope</span>.<span class="ruby-identifier">where</span>( <span class="ruby-operator">*</span><span class="ruby-identifier">args</span> )
      <span class="ruby-keyword">else</span>
        <span class="ruby-identifier">prevailing_scope</span> = <span class="ruby-identifier">none</span>()
        <span class="ruby-keyword">break</span>
      <span class="ruby-keyword">end</span>
    <span class="ruby-keyword">end</span>
  <span class="ruby-keyword">end</span>

  <span class="ruby-keyword">return</span> <span class="ruby-identifier">prevailing_scope</span>
<span class="ruby-keyword">end</span></pre>
              </div>
            </div>
          </div>
        <div class="method">
          <div class="title method-title" id="method-i-secure_with">
              <b>secure_with</b>( map )
            <a href="../../../../classes/Hoodoo/ActiveRecord/Secure/ClassMethods.html#method-i-secure_with" name="method-i-secure_with" class="permalink">Link</a>
          </div>

            <div class="description">
              <p>Declare the mapping between database columns and Session scoping entries.
See <a href="ClassMethods.html#method-i-secure">secure</a> for details and
examples.</p>

<p>Parameters:</p>
<dl class="rdoc-list note-list"><dt><code>map</code>
<dd>
<p>A Hash of String or Symbol keys and values that gives the secure mapping
details. The keys are names of fields in the model. The values are names of
fields in the <a
href="../../Services/Session.html#attribute-i-scoping">Hoodoo::Services::Session#scoping</a>
object, or can be a Hash of options; see <a
href="ClassMethods.html#method-i-secure">secure</a> for full details and
examples.</p>
</dd></dl>
            </div>



            <div class="sourcecode">
              <p class="source-link">
                Source:
                <a href="javascript:toggleSource('method-i-secure_with_source')" id="l_method-i-secure_with_source">show</a>
              </p>
              <div id="method-i-secure_with_source" class="dyn-source">
                <pre><span class="ruby-comment"># File lib/hoodoo/active/active_record/secure.rb, line 417</span>
<span class="ruby-keyword">def</span> <span class="ruby-keyword ruby-title">secure_with</span>( <span class="ruby-identifier">map</span> )
  <span class="ruby-keyword">self</span>.<span class="ruby-identifier">nz_co_loyalty_hoodoo_secure_with</span> = <span class="ruby-identifier">map</span>
<span class="ruby-keyword">end</span></pre>
              </div>
            </div>
          </div>
        <div class="method">
          <div class="title method-title" id="method-i-secured_with">
              <b>secured_with</b>()
            <a href="../../../../classes/Hoodoo/ActiveRecord/Secure/ClassMethods.html#method-i-secured_with" name="method-i-secured_with" class="permalink">Link</a>
          </div>

            <div class="description">
              <p>Retrieve the mapping declared between database columns and Session scoping
entries via <a
href="ClassMethods.html#method-i-secure_with">secure_with</a>. Returns a
map as passed to <a
href="ClassMethods.html#method-i-secure_with">secure_with</a>, or
<code>nil</code> if no such declaration has been made.</p>
            </div>



            <div class="sourcecode">
              <p class="source-link">
                Source:
                <a href="javascript:toggleSource('method-i-secured_with_source')" id="l_method-i-secured_with_source">show</a>
              </p>
              <div id="method-i-secured_with_source" class="dyn-source">
                <pre><span class="ruby-comment"># File lib/hoodoo/active/active_record/secure.rb, line 425</span>
<span class="ruby-keyword">def</span> <span class="ruby-keyword ruby-title">secured_with</span>
  <span class="ruby-keyword">self</span>.<span class="ruby-identifier">nz_co_loyalty_hoodoo_secure_with</span>
<span class="ruby-keyword">end</span></pre>
              </div>
            </div>
          </div>
</div>

    </div>
  </body>
</html>
